home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Views / Sources / UTearOffMenuView.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  18.2 KB  |  564 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UTearOffMenu.cp
  3. // Copyright © 1988-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UTEAROFFMENUVIEW__
  7. #include "UTearOffMenuView.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. //    #ifndef __UAPPLICATION__
  13. //    #include "UApplication.h"
  14. //    #endif
  15.  
  16. #if qContainer
  17.     #ifndef __UCONTAINER__
  18.     #include "UContainer.h"
  19.     #endif
  20. #endif
  21.  
  22. #ifndef __UDISPATCHER__
  23. #include "UDispatcher.h"
  24. #endif
  25.  
  26. #ifndef __UFAILURE__
  27. #include "UFailure.h"
  28. #endif
  29.  
  30. #ifndef __UGEOMETRY__
  31. #include "UGeometry.h"
  32. #endif
  33.  
  34. #ifndef __UMACAPPGLOBALS__
  35. #include "UMacAppGlobals.h"
  36. #endif
  37.  
  38. #ifndef __UMACAPPUTILITIES__
  39. #include "UMacAppUtilities.h"
  40. #endif
  41.  
  42. #ifndef __UPATCH__
  43. #include "UPatch.h"
  44. #endif
  45.  
  46. #ifndef __UWINDOW__
  47. #include "UWindow.h"
  48. #endif
  49.  
  50. // Toolbox
  51.  
  52. #ifndef __DIALOGS__
  53. #include <Dialogs.h>
  54. #endif
  55.  
  56. #ifndef __ERRORS__
  57. #include <Errors.h>
  58. #endif
  59.  
  60. #ifndef __LOWMEM__
  61. #include <LowMem.h>
  62. #endif
  63.  
  64. #ifndef __TEXTEDIT__
  65. #include <TextEdit.h>
  66. #endif
  67.  
  68. #ifndef __TOOLUTILS__
  69. #include <ToolUtils.h>
  70. #endif
  71.  
  72. // CALib
  73.  
  74. #if qContainer
  75.     #ifndef _CALIB_
  76.     #include "CALib.h"
  77.     #endif
  78. #endif
  79.  
  80. //========================================================================================
  81. // CLASS TShowTearOffWindowCommand
  82. //========================================================================================
  83. #undef Inherited
  84. #define Inherited TCommand
  85.  
  86. #pragma segment TearOffDoCommand
  87. MA_DEFINE_CLASS_M1(TShowTearOffWindowCommand, Inherited);
  88.  
  89. //----------------------------------------------------------------------------------------
  90. // TShowTearOffWindowCommand constructor
  91. //----------------------------------------------------------------------------------------
  92. #pragma segment TearOffDoCommand
  93.  
  94. TShowTearOffWindowCommand::TShowTearOffWindowCommand()
  95. {
  96.     fTearOffWindow = NULL;
  97.     fWhere = gZeroPt;
  98. } // TShowTearOffWindowCommand::TShowTearOffWindowCommand
  99.  
  100. //----------------------------------------------------------------------------------------
  101. // TShowTearOffWindowCommand destructor
  102. //----------------------------------------------------------------------------------------
  103. #pragma segment MADestructorRes
  104.  
  105. TShowTearOffWindowCommand::~TShowTearOffWindowCommand()
  106. {
  107. }
  108.  
  109. //----------------------------------------------------------------------------------------
  110. // TShowTearOffWindowCommand::IShowTearOffWindowCommand: 
  111. //----------------------------------------------------------------------------------------
  112. #pragma segment TearOffDoCommand
  113.  
  114. void TShowTearOffWindowCommand::IShowTearOffWindowCommand(TWindow* tearOffWindow,
  115.                                                          CPoint where)
  116. {
  117.     this->ICommand(cNoCommand, NULL, kCantUndo, kDoesNotCauseChange, NULL);
  118.     fTearOffWindow = tearOffWindow;
  119.     fWhere = where;
  120. } // TShowTearOffWindowCommand::IShowTearOffWindowCommand 
  121.  
  122. //----------------------------------------------------------------------------------------
  123. // TShowTearOffWindowCommand::DoIt: 
  124. //----------------------------------------------------------------------------------------
  125. #pragma segment TearOffDoCommand
  126.  
  127. void TShowTearOffWindowCommand::DoIt()    // override 
  128. {
  129.     if (fTearOffWindow)
  130.     {
  131.         fTearOffWindow->Show(FALSE, FALSE);            // Hide the window so that Open will call
  132.         fTearOffWindow->fMustForceOnScreen = TRUE;    // ForceOnScreen before showing
  133.         fTearOffWindow->fForcedOnScreen = FALSE;
  134.         
  135.         fTearOffWindow->Locate(fWhere, kDontInvalidate);
  136.         
  137. #if qContainer
  138. // ••• MDR
  139.         if (gContainerLib)
  140.         {
  141.             CARegisterFloatingWindow(fTearOffWindow->fWMgrWindow);
  142.             FailOSErr(CAError());
  143.         }
  144. #endif
  145.  
  146.         fTearOffWindow->Open();                        // show the torn-off window 
  147.         
  148.         fTearOffWindow->Select();                    // select the torn-off window 
  149.     }
  150. } // TShowTearOffWindowCommand::DoIt 
  151.  
  152.  
  153. //========================================================================================
  154. // CLASS TTearOffMenuViewTracker
  155. //========================================================================================
  156. #undef Inherited
  157. #define Inherited TTracker
  158.  
  159. #pragma segment TearOffInit
  160. MA_DEFINE_CLASS_M1(TTearOffMenuViewTracker, Inherited);
  161.  
  162. //----------------------------------------------------------------------------------------
  163. // TTearOffMenuViewTracker::TTearOffMenuViewTracker: Empty constructor to satisfy the compiler.
  164. //----------------------------------------------------------------------------------------
  165. #pragma segment ConstructorRes
  166.  
  167. TTearOffMenuViewTracker::TTearOffMenuViewTracker()
  168. {
  169. } // TTearOffMenuViewTracker::TTearOffMenuViewTracker
  170.  
  171. //----------------------------------------------------------------------------------------
  172. // TTearOffMenuViewTracker destructor
  173. //----------------------------------------------------------------------------------------
  174. #pragma segment MADestructorRes
  175.  
  176. TTearOffMenuViewTracker::~TTearOffMenuViewTracker()
  177. {
  178. }
  179.  
  180. //----------------------------------------------------------------------------------------
  181. // TTearOffMenuViewTracker::ITearOffMenuViewTracker: 
  182. //----------------------------------------------------------------------------------------
  183. #pragma segment TearOffInit
  184.  
  185. void TTearOffMenuViewTracker::ITearOffMenuViewTracker(CommandNumber itsCommandNumber,
  186.                                                              TCommandHandler* itsContext,
  187.                                                              Boolean canUndo,
  188.                                                              Boolean causesChange,
  189.                                                              TObject* objectToNotify,
  190.                                                               TView* itsView,
  191.                                                              TScroller* itsScroller,
  192.                                                              const VPoint& itsMouse)
  193. {
  194.     this->ITracker(itsCommandNumber, itsContext, canUndo, causesChange, objectToNotify,
  195.                     itsView, itsScroller, itsMouse);
  196. } // TTearOffMenuViewTracker::ITearOffMenuViewTracker 
  197.  
  198. //----------------------------------------------------------------------------------------
  199. // TTearOffMenuViewTracker::IsReadyToPost: 
  200. //----------------------------------------------------------------------------------------
  201. #pragma segment TearOffDoCommand
  202.  
  203. Boolean TTearOffMenuViewTracker::IsReadyToPost()    // override
  204. {
  205.     ++(gDispatcher->fEventLevel);
  206.     this->Process();                // perform this right away
  207.     --(gDispatcher->fEventLevel);
  208.     return FALSE;
  209. } // TTearOffMenuViewTracker::IsReadyToPost 
  210.  
  211.  
  212. //========================================================================================
  213. // CLASS TTearOffTracker
  214. //========================================================================================
  215. #undef Inherited
  216. #define Inherited TTearOffMenuViewTracker
  217.  
  218. #pragma segment TearOffInit
  219. MA_DEFINE_CLASS_M1(TTearOffTracker, Inherited);
  220.  
  221. //----------------------------------------------------------------------------------------
  222. // TTearOffTracker constructor
  223. //----------------------------------------------------------------------------------------
  224. #pragma segment TearOffInit
  225.  
  226. TTearOffTracker::TTearOffTracker()
  227. {
  228.     fExitTracking = FALSE;
  229.     fOrigin = gZeroPt;
  230.     fTearOffMenu = NULL;
  231.     fTearOffWindowOutline = NULL;
  232. } // TTearOffTracker::TTearOffTracker
  233.  
  234. //----------------------------------------------------------------------------------------
  235. // TTearOffTracker::ITearOffTracker: 
  236. //----------------------------------------------------------------------------------------
  237. #pragma segment TearOffInit
  238.  
  239. void TTearOffTracker::ITearOffTracker(CPoint hitPt,
  240.                                              TTearOffMenuView* tearOffMenu)
  241. {
  242.     VPoint theMouse(hitPt);
  243.     this->ITearOffMenuViewTracker(cNoCommand, NULL, kCantUndo, kDoesNotCauseChange, NULL,
  244.                     NULL, NULL, theMouse);
  245.  
  246.     fFreeOnCompletion = FALSE;
  247.  
  248.     fTearOffMenu = tearOffMenu;
  249.  
  250.     FailInfo fi;
  251.     Try(fi)
  252.     {
  253.         fTearOffWindowOutline = MakeNewRgn();
  254.  
  255.         fi.Success();
  256.     }
  257.     else
  258.     {
  259.         this->Free();
  260.         fi.ReSignal();
  261.     }
  262. } // TTearOffTracker::ITearOffTracker 
  263.  
  264. //----------------------------------------------------------------------------------------
  265. // TTearOffTracker::Free: 
  266. //----------------------------------------------------------------------------------------
  267. #pragma segment TearOffClose
  268.  
  269. TTearOffTracker::~TTearOffTracker()
  270. {
  271.     fTearOffWindowOutline = DisposeIfRgnHandle(fTearOffWindowOutline);
  272. } // TTearOffTracker::Free 
  273.  
  274. //----------------------------------------------------------------------------------------
  275. // TTearOffTracker::DoIt: 
  276. //----------------------------------------------------------------------------------------
  277. #pragma segment TearOffDoCommand
  278.  
  279. void TTearOffTracker::DoIt()
  280. {
  281.     if (!fExitTracking)                    // ensure that we didn't exit the tracking loop
  282.     {
  283.         TWindow * aTearOffWindow = fTearOffMenu->fTearOffWindow;
  284.  
  285.         CPoint where = ((CRect &) (*fTearOffWindowOutline)->rgnBBox)[topLeft] + aTearOffWindow->fContentRegionInset;
  286.  
  287.         if (aTearOffWindow != NULL)
  288.         {
  289.             // NOTE: we can't just move and show the tear off window here because the menu
  290.             // that we want to tearx off is currently displayed on the screen and the menu
  291.             // manager has cached the bits underneath the currently displayed menu and we
  292.             // might be moving our floating window into that territory thus invalidating
  293.             // the menu manager's cache (which the menu manager will blit back in place
  294.             // momentarily). To work-around this "feature" we'll simply post a command
  295.             // which will do the work later. Isn't MacApp wonderful!
  296.             TShowTearOffWindowCommand * aShowTearOffWindowCmd = new TShowTearOffWindowCommand;
  297.             aShowTearOffWindowCmd->IShowTearOffWindowCommand(aTearOffWindow, where);
  298.             fTearOffMenu->PostCommand(aShowTearOffWindowCmd);
  299.         }
  300.     }
  301. } // TTearOffTracker::DoIt 
  302.  
  303. //----------------------------------------------------------------------------------------
  304. // TTearOffTracker::TrackFeedback: 
  305. //----------------------------------------------------------------------------------------
  306. #pragma segment TearOffDoCommand
  307.  
  308. void TTearOffTracker::TrackFeedback(TrackPhase /* aTrackPhase */,
  309.                                         const VPoint& /* anchorPoint */,
  310.                                         const VPoint& /* previousPoint */,
  311.                                         const VPoint& /* nextPoint */,
  312.                                         Boolean mouseDidMove,
  313.                                         Boolean /* turnItOn */)
  314. {
  315.     if (mouseDidMove && !EmptyRgn(fTearOffWindowOutline))
  316.     {
  317.         PenPat(&qd.gray);
  318.         FrameRgn(fTearOffWindowOutline);        // draw/erase 
  319.     }
  320. } // TTearOffTracker::TrackFeedback 
  321.  
  322. //----------------------------------------------------------------------------------------
  323. // TTearOffTracker::TrackMouse: 
  324. //----------------------------------------------------------------------------------------
  325. #pragma segment TearOffDoCommand
  326.  
  327. TTracker* TTearOffTracker::TrackMouse(TrackPhase aTrackPhase,
  328.                                              VPoint& ,
  329.                                              VPoint& previousPoint,
  330.                                              VPoint& nextPoint,
  331.                                              Boolean)
  332. {
  333.     TWindow * aTearOffWindow;
  334.     short verticalOffset;
  335.     short horizontalOffset;
  336.     Boolean rgnsWereBuilt;
  337.  
  338.     CPoint qdPt = nextPoint.ToPoint();
  339.     fExitTracking =!PtInRgn(qdPt, fTearOffMenu->fTearOffTrackingRegion);
  340.  
  341.     if (aTrackPhase == trackBegin)
  342.     {
  343.         aTearOffWindow = fTearOffMenu->fTearOffWindow;
  344.         if (aTearOffWindow != NULL)
  345.         {
  346.             rgnsWereBuilt = aTearOffWindow->BuildWindowRegions(kBuild);
  347.             GetWindowStructureRgn(aTearOffWindow->fWMgrWindow, fTearOffWindowOutline);
  348.             aTearOffWindow->BuildWindowRegions(rgnsWereBuilt);
  349.  
  350.             // move the outline to the topleft of the window mgr graf port 
  351.             OffsetRgn(fTearOffWindowOutline, -(*fTearOffWindowOutline)->rgnBBox.left, -(*fTearOffWindowOutline)->rgnBBox.top);
  352.  
  353.             // move the outline so that it's centered at the mouse 
  354.             verticalOffset = (((CRect &) (*fTearOffWindowOutline)->rgnBBox).GetLength(vSel)) / 2;
  355.             horizontalOffset = (((CRect &) (*fTearOffWindowOutline)->rgnBBox).GetLength(hSel)) / 2;
  356.             OffsetRgn(fTearOffWindowOutline, (short)(previousPoint.h - horizontalOffset), (short)(previousPoint.v - verticalOffset));
  357.         }
  358.         //aTearOffWindow != NULL
  359.     }
  360.     else
  361.         OffsetRgn(fTearOffWindowOutline, (short)(nextPoint.h - previousPoint.h), (short)(nextPoint.v - previousPoint.v));
  362.     return this;
  363. } // TTearOffTracker::TrackMouse 
  364.  
  365. //----------------------------------------------------------------------------------------
  366. // TTearOffTracker::IsDoneTracking: 
  367. //----------------------------------------------------------------------------------------
  368. #pragma segment TearOffDoCommand
  369.  
  370. Boolean TTearOffTracker::IsDoneTracking()// override 
  371. {
  372.     return ((!StillDown()) || fExitTracking);
  373. } // TTearOffTracker::IsDoneTracking 
  374.  
  375.  
  376. //========================================================================================
  377. // CLASS TTearOffMenuView
  378. //========================================================================================
  379. #undef Inherited
  380. #define Inherited TMenuView
  381.  
  382. #pragma segment TearOffInit
  383. MA_DEFINE_CLASS_M1(TTearOffMenuView, Inherited);
  384.  
  385. //----------------------------------------------------------------------------------------
  386. // TTearOffMenuView constructor
  387. //----------------------------------------------------------------------------------------
  388. #pragma segment TearOffInit
  389.  
  390. TTearOffMenuView::TTearOffMenuView()
  391. {
  392.     fTearOffTracker = NULL;
  393.     fTearOffTrackingRegion = NULL;
  394.     fTearOffWindow = NULL;
  395. } // TTearOffMenuView::TTearOffMenuView
  396.  
  397. //----------------------------------------------------------------------------------------
  398. // TTearOffMenuView::ITearOffMenuView: 
  399. //----------------------------------------------------------------------------------------
  400. #pragma segment TearOffInit
  401.  
  402. void TTearOffMenuView::ITearOffMenuView(ResNumber rsrcID,
  403.                                                short menuWidth,
  404.                                                short menuHeight,
  405.                                                TWindow* tearOffWindow)
  406. {
  407.     this->IMenuView(rsrcID, menuWidth, menuHeight);
  408.  
  409.     FailInfo fi;
  410.     Try(fi)
  411.     {
  412.         fTearOffTrackingRegion = MakeNewRgn();
  413.         fTearOffWindow = tearOffWindow;
  414.  
  415.         this->InstallTearOffTracker();
  416.         fi.Success();
  417.     }
  418.     else
  419.     {
  420.         this->Free();
  421.         fi.ReSignal();
  422.     }
  423. } // TTearOffMenuView::ITearOffMenuView 
  424.  
  425. //----------------------------------------------------------------------------------------
  426. // TTearOffMenuView::InstallTearOffTracker: For the sake of efficiency when tracking a
  427. // tear-off, we'll create the tear-off tracker and keep it with us, so we don't need to
  428. // allocate a new tracker every time we tear off a menu. If you want a different tracker
  429. // in your subclass of TTearOffMenuView, then override this method.
  430. //----------------------------------------------------------------------------------------
  431. #pragma segment TearOffInit
  432.  
  433. void TTearOffMenuView::InstallTearOffTracker()
  434. {
  435.     TTearOffTracker * tearOffTracker;
  436.  
  437.     tearOffTracker = new TTearOffTracker;
  438.     tearOffTracker->ITearOffTracker(gZeroPt, this);
  439.     fTearOffTracker = tearOffTracker;
  440. } // TTearOffMenuView::InstallTearOffTracker 
  441.  
  442. //----------------------------------------------------------------------------------------
  443. // TTearOffMenuView::Free: 
  444. //----------------------------------------------------------------------------------------
  445. #pragma segment TearOffClose
  446.  
  447. TTearOffMenuView::~TTearOffMenuView()
  448. {
  449.     fTearOffTracker = (TTearOffTracker *)FreeIfObject(fTearOffTracker);
  450.     fTearOffTrackingRegion = DisposeIfRgnHandle(fTearOffTrackingRegion);
  451. } // TTearOffMenuView::Free 
  452.  
  453. //----------------------------------------------------------------------------------------
  454. // TTearOffMenuView::HandleChooseMessage: 
  455. //----------------------------------------------------------------------------------------
  456. #pragma segment TearOffRes
  457.  
  458. void TTearOffMenuView::HandleChooseMessage(short,
  459.                                                   MenuRef,
  460.                                                   CRect& menuRect,
  461.                                                   CPoint hitPt,
  462.                                                   short& whichItem)// override 
  463. {
  464.     short newItem;
  465.     CRect hitRect;
  466.     Boolean oldObjectPerm;
  467.     TToolboxEvent * event = NULL;
  468.     EventRecord theEventRecord;
  469.     Boolean saveTrackingInMenu;
  470.  
  471.     // so that trackers know that they're tracking in menus 
  472.     saveTrackingInMenu = gTrackingInMenu;
  473.     gTrackingInMenu = TRUE;
  474.  
  475.     newItem = kNoMenuItem;                        // default return 
  476.  
  477.     if (this->IsEnabled())                            // menu enabled 
  478.     {
  479.         // see if CPoint is within hit area 
  480.         CRect hitRect = GetQDExtent() + fBorder;
  481.         if (hitRect.Contains(hitPt))            // in menu view (not border) 
  482.         {
  483.             // NOTE: Either your subclass of TTearOffMenuView should override
  484.             // DoMouseCommand or one of TTearOffMenuView's view's subview's should
  485.             // override DoMouseCommand so that it creates and posts a TTracker. SubClasses
  486.             // of TTearOffMenuViewTrackers will be tracked immediately because of the its
  487.             // override of IsReadyToPost. So, when we're done with HandleMouseDown below,
  488.             // we simply tell the menu manager that no menu item was selected, ie
  489.             // newItem == kNoMenuItem.
  490.  
  491.             theEventRecord.what = mouseDown;
  492.             theEventRecord.message = 0;
  493.             theEventRecord.when = TickCount();
  494.             theEventRecord.where = hitPt;
  495.             theEventRecord.modifiers = 0;
  496.             
  497.             if (Button())
  498.                 theEventRecord.modifiers |= btnState;
  499.                 
  500.             if (IsCommandKeyDown())
  501.                 theEventRecord.modifiers |= cmdKey;
  502.                 
  503.             if (IsOptionKeyDown())
  504.                 theEventRecord.modifiers |= optionKey;
  505.                 
  506.             oldObjectPerm = AllocateObjectsFromPerm(FALSE);
  507.             event = new TToolboxEvent;
  508.             AllocateObjectsFromPerm(oldObjectPerm);
  509.             event->IToolboxEvent(NULL, theEventRecord);
  510.             event->fClickCount = gDispatcher->fClickCount;
  511.             event->fAffectsMenus = FALSE;
  512.             this->HandleMouseDown(hitPt, event, gStdHysteresis);
  513.             event = (TToolboxEvent *)FreeIfObject(event);
  514.         }
  515.         else
  516.         {                                        // determine if we should track a tear off image
  517.             LocalToGlobal(hitPt);
  518.             if (PtInRgn(hitPt, this->GetTearOffTrackingRegion(menuRect)))
  519.             {
  520.                 fTearOffTracker->fInitialPt = hitPt;
  521.                 this->PostCommand(fTearOffTracker);
  522.             }
  523.         }
  524.     }
  525.     else
  526.         this->UpdateHighlight(whichItem, newItem);    // Update highlighting 
  527.  
  528.     gTrackingInMenu = saveTrackingInMenu;
  529.  
  530.     // Tell MenuManager about new item 
  531.     whichItem = newItem;
  532. } // TTearOffMenuView::HandleChooseMessage 
  533.  
  534. //----------------------------------------------------------------------------------------
  535. // TTearOffMenuView::GetTearOffTrackingRegion: This function returns
  536. // fTearOffTrackingRegion
  537. //----------------------------------------------------------------------------------------
  538. #pragma segment TearOffRes
  539.  
  540. RgnHandle TTearOffMenuView::GetTearOffTrackingRegion(const CRect& menuRect)
  541. {
  542.     if (EmptyRgn(fTearOffTrackingRegion))
  543.     {
  544.         CRect rgnRect = menuRect;
  545.         
  546.         // calculate the tracking region for the tearoff image
  547.         LocalToGlobal(rgnRect[topLeft]);
  548.         LocalToGlobal(rgnRect[botRight]);
  549.         rgnRect.Inset(CPoint(-kTearOffMargin, -kTearOffMargin));
  550.  
  551.         CTemporaryRegion tempRgn;
  552.  
  553.         RectRgn(tempRgn, rgnRect);
  554.         DiffRgn(GetGrayRgn(), tempRgn, fTearOffTrackingRegion);
  555.         InsetRgn(fTearOffTrackingRegion, 4, 4);
  556.     }
  557.     return fTearOffTrackingRegion;
  558. } // TTearOffMenuView::GetTearOffTrackingRegion 
  559.  
  560. //----------------------------------------------------------------------------------------
  561. // End of UTearOffMenuView.cp
  562.  
  563. #pragma segment Inline
  564.